﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenCvSharp;
using ExpreRec.Logic.Preprocessing;
using ExpreRec.Logic.Util;

namespace ExpreRec.Logic.FaceDetection
{
    public class HaarFaceDetector
    {
        private string xmlHaarcascade;
        private int maximumSize;
        private double scaleFactor;
        private int minNeighbors;
        private int minFaceSize;
        private HaarDetectionType haarDetectionType;

        public HaarFaceDetector(string xmlHaarcascade = null, int maximumSize = 1024, double scaleFactor = 1.0850, int minNeighbors = 3, int minFaceSize = 30, HaarDetectionType haarDetectionType = HaarDetectionType.FindBiggestObject|HaarDetectionType.DoCannyPruning)
        {
            if (xmlHaarcascade == null)
                this.xmlHaarcascade = Const.XmlHaarcascadeAlt;
            else this.xmlHaarcascade = xmlHaarcascade;

            this.maximumSize = maximumSize;
            this.scaleFactor = scaleFactor;
            this.minNeighbors = minNeighbors;
            this.minFaceSize = minFaceSize;
            this.haarDetectionType = haarDetectionType;
        }

        public IList<IplImage> Detect(IplImage img)
        {
            IList<IplImage> res = new List<IplImage>();

            //resize the image if it is too large
            int max = Math.Max(img.Size.Width, img.Size.Height);

            IplImage original = img;

            if (max > maximumSize)
            {
                double ratio = (double)max / maximumSize;
                img = Processor.ReSize(original, ratio, Interpolation.Linear);
            }
            else
                img = original.Clone();

            //CvWindow.ShowImages(img);
            //convert the image to gray, and equalize the image using histograph
            using (img)
            using (IplImage grayImage = Processor.RGBToGray(img))
            using (IplImage equalizedImage = Processor.EqualizeHist(grayImage))
            {
                CvSeq<CvAvgComp> faces = null;

                using (CvHaarClassifierCascade cascade = CvHaarClassifierCascade.FromFile(xmlHaarcascade))
                using (CvMemStorage storage = new CvMemStorage())
                {
                    storage.Clear();

                    //return the detected faces
                    faces = Cv.HaarDetectObjects(equalizedImage, cascade, storage, scaleFactor, minNeighbors, haarDetectionType, new CvSize(minFaceSize, minFaceSize));

                    for (int i = 0; i < faces.Total; i++)
                    {
                        res.Add(img.GetSubImage(faces[i].Value.Rect));
                        //CvWindow.ShowImages(res[i]);
                    }
                }
                return res;
            }
        }
    }
}
